import socket
import struct
import time
import pyautogui
import PIL.ImageGrab
from io import BytesIO
import configparser
import threading
import os


class CheckingClient:
    def __init__(self, host='127.0.0.1', port=2055):
        self.host = host
        self.port = port
        self.config_path = 'Config.ini'
        self.socket = self._create_socket()

    def _create_socket(self):
        config = configparser.ConfigParser()
        if not os.path.exists(self.config_path):
            raise FileNotFoundError(f"配置文件 {self.config_path} 不存在")
        config.read(self.config_path, encoding='utf-8')
        self.host = config.get("Server", "host", fallback='127.0.0.1')
        self.port = int(config.get("Server", "port", fallback=2055))
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        return sock

    def connect(self):
        """连接到服务器"""
        self.socket.connect((self.host, self.port))
        print(f"已连接到服务器 {self.host}:{self.port}")

    def take_screenshot(self):
        try:
            screenshot = PIL.ImageGrab.grab()
            screenshot = screenshot.resize((screenshot.width, screenshot.height))  # 缩小尺寸
            buffered = BytesIO()
            screenshot.save(buffered, format="JPEG", quality=80)  # 保存为 JPEG 格式
            img_data = buffered.getvalue()
            img_length = len(img_data)
            print(f"压缩后截图大小: {img_length} 字节")

            # 发送消息类型和长度
            message_type = 0xF2
            self.socket.sendall(struct.pack('>B', message_type) + struct.pack('>I', img_length))

            # 分块发送截图数据
            chunk_size = 4096  # 每次发送 4KB
            for i in range(0, img_length, chunk_size):
                chunk = img_data[i:i + chunk_size]
                self.socket.sendall(chunk)
        except Exception as e:
            print(f"截图或发送失败: {e}")

    def take_ok(self, type=0xFF):
        try:
            message_type = type
            self.socket.sendall(struct.pack('>B', message_type))
        except Exception as e:
            print(f"回复OK失败: {e}")

    def click(self, x, y):
        """模拟鼠标点击"""
        pyautogui.click(x, y)
        print(f"已点击坐标: ({x}, {y})")

    def press_key(self, key):
        """模拟键盘按键"""
        pyautogui.press(key)
        print(f"已按下按键: {key}")

    def handle_server_messages(self):
        while True:
            header = self.socket.recv(1)
            if header:
                message_type = struct.unpack('>B', header)[0]
                if message_type == 0x01:  # 点击消息
                    raw_data = self.socket.recv(8)  # 读取点击坐标
                    x, y = struct.unpack('>II', raw_data)
                    if not (x == 0 and y == 0):
                        self.click(x, y)
                    self.take_ok(0xF1)
                    print("接收到Click指令，已完成")
                elif message_type == 0x02:  # 截图消息
                    self.take_screenshot()
                    time.sleep(0.2)
                    print("接收到截图指令，已完成")
                elif message_type == 0x03:  # 键盘消息
                    # 读取按键数据长度
                    raw_key_length = self.socket.recv(4)
                    key_length = struct.unpack('>I', raw_key_length)[0]

                    # 读取按键数据
                    key_bytes = self.socket.recv(key_length)
                    key = key_bytes.decode('utf-8')  # 解码为字符串

                    # 执行按键操作
                    self.press_key(key)
                    self.take_ok(0xF3)
                    print(f"接收到键盘指令，按键: {key}，已完成")
                else:
                    print(f"未知消息类型: {message_type}")
            time.sleep(0.2)

    def start(self):
        """启动客户端"""
        self.connect()
        while True:
            try:
                self.handle_server_messages()
            except ConnectionError as e:
                print(f"连接断开，尝试重新连接: {e}")
                time.sleep(3)
                self.socket = self._create_socket()
                if not self.socket:
                    print("无法重新连接服务器")
                    break


if __name__ == "__main__":
    client = CheckingClient()
    client.start()
